home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / OpenDocSetup / ODMemoryCP.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  39.9 KB  |  1,444 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODMemoryCP.cpp
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <10>    11.09.1996    NP        1386074: Not using mimimum size for lower
  13.                                     bound.
  14.          <9>    17.07.1996    NP        1363849: Can't open desk accessories.
  15.          <8>    15.07.1996    NP        1368246: OD Setup: The dialog font is
  16.                                     hard-coded.
  17.          <7>    12.07.1996    NP        1367619, 1365750: AreODProcessesRunning had
  18.                                     break statements instead of continue
  19.                                     statements.
  20.          <6>     6/28/96    TJ        Fixed Non-Debug Build.
  21.          <5>     6/27/96    NP        10002: Launch time speedups.
  22.          <4>     6/26/96    NP        10002: Launch time speedups.
  23.          <3>     6/24/96    NP        10002: Launch time speedups
  24.          <2>     6/23/96    NP        10002: Launch time speedups.
  25.          <1>     6/21/96    NP        first checked in
  26.  
  27.     To Do:
  28. */
  29.  
  30. #ifndef ODMEMORYCP_H
  31. #include "ODMemoryCP.h"
  32. #endif
  33.  
  34. #ifndef SIZERC_H
  35. #include "SIZERC.h"
  36. #endif
  37.  
  38. #ifndef BETTERFINDFOLDER_H
  39. #include "BetterFindFolder.h"
  40. #endif
  41.  
  42. #ifndef PREFSFILE_H
  43. #include "PrefsFile.h"
  44. #endif
  45.  
  46. #ifndef ST_MACCLASSES_H
  47. #include "ST_MacClasses.h"
  48. #endif
  49.  
  50. #ifndef _PROCESSSTUFF_
  51. #include "ProcessStuff.h"
  52. #endif
  53.  
  54. #ifndef _ODPRCS_
  55. #include "ODPrcs.h"
  56. #endif
  57.  
  58. #ifndef _SHELLDEF_
  59. #include "ShellDef.h"
  60. #endif
  61.  
  62. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  63. #include "StdDefs.xh"
  64. #endif
  65.  
  66. #ifndef __DIALOGS__
  67. #include <Dialogs.h>
  68. #endif
  69.  
  70. #ifndef __ICONS__
  71. #include <Icons.h>
  72. #endif
  73.  
  74. #ifndef __MENUS__
  75. #include <Menus.h>
  76. #endif
  77.  
  78. #ifndef __DEVICES__
  79. #include <Devices.h>
  80. #endif
  81.  
  82. #ifndef __STRINGS__
  83. #include <Strings.h>
  84. #endif
  85.  
  86. #ifndef __FONTS__
  87. #include <Fonts.h>
  88. #endif
  89.  
  90. #ifndef __APPLEEVENTS__
  91. #include <AppleEvents.h>
  92. #endif
  93.  
  94. #ifndef __TEXTUTILS__
  95. #include <TextUtils.h>
  96. #endif
  97.  
  98. #ifndef __TOOLUTILS__
  99. #include <ToolUtils.h>
  100. #endif
  101.  
  102. #define    kMainDialogID        128
  103. #define    kMenuBarID            128
  104. #define    kAppleMenuID        1
  105. #define        kAboutItem        1
  106. #define    kFileMenuID            2
  107. #define    kEditMenuID            3
  108.  
  109. #define    kNormalIconID        128
  110. #define    kUpArrowIconID        129
  111. #define    kDownArrowIconID    130
  112.  
  113. enum {
  114.     kOKButton = 1,
  115.     kCancelButton,    // 2
  116.     kSizeText,        // 3
  117.     kArrowBottom,    // 4
  118.     kArrowTop,        // 5
  119.     kArrowControl,    // 6
  120.     kMiscText1,        // 7 not used
  121.     kMiscText2,        // 8 not used
  122.     kMiscText3,        // 9 "K"
  123.     kOKHilite        // 10 not used
  124. };
  125.  
  126. #define kAtSysStartupRadio            14
  127. #define kWhenFirstDocOpenedRadio    17
  128. #define kAtSysShutdownRadio            15
  129. #define kWhenLastDocClosedRadio        16
  130. #define kStartStopButton            13
  131. #define kProcessInfoText            20
  132.  
  133. #define kSelected 1
  134.  
  135. // STR
  136. #define kOpenDocIsStoppedID            128
  137. #define kOpenDocIsRunningID            129
  138. #define kStartID                    130
  139. #define kStopID                        131
  140. #define kOpenDocIsRunningNoStopID    132
  141.  
  142. //#define    kSleepTime            0xFFFFFFFF // Don't send any idle events.
  143. #define    kSleepTime            60 // 
  144.  
  145. // CONSTANTS FOR MESSAGE SENDING
  146. #define kNoMessage                0 // used to see if the process returns noErr
  147. #define kStartAtSysStartup        1
  148. #define kStartAtFirstDocOpen    2
  149. #define kRunUntilQuitEvent        3
  150. #define kShutdownAtLastDocQuit    4
  151.  
  152.  
  153. pascal void MyUserItemProc (DialogPtr dlog, short item);
  154. UserItemUPP        gUserItemUPP = NewUserItemProc (MyUserItemProc);
  155.  
  156. void    DisplayFinalErrors();
  157. void    SetWindowPos();
  158. void    WriteWindowPos(DialogPtr d);
  159. void    CopyPascalString(StringPtr destStr, StringPtr srcStr);
  160. void    DoDialogSetup(DialogPtr dialog);
  161. Boolean    DoDialogHits(DialogPtr dialog, short itemHit);
  162. void    ODSetupDebugStr(char* cString);
  163. void    DoMemorySettingHits(DialogPtr dialog, short itemHit);
  164. void    DoWhenToRunHits(DialogPtr dialog, short itemHit);
  165. void    DoStopStartButtonHits(DialogPtr dialog, short itemHit);
  166. OSErr    SendControlCall(DialogPtr dialog, ProcessSerialNumber* psn,
  167.                         long controlConstant);
  168. void    SetPrefs(long controlConstant);
  169. void    CheckForRunningSystemProcesses(DialogPtr dialog);
  170. void    SetButtonRunState(DialogPtr dialog, Boolean odISRunning,
  171.                             Boolean odDocsAreRunning);
  172. OSErr    LaunchSystemProcess(ProcessSerialNumber* psn);
  173. void    AreODProcessesRunning(DialogPtr dialog, ProcessSerialNumber* psn,
  174.                                 Boolean& odDocsAreRunning);
  175. void    SetRunTextForRunningState(DialogPtr dialog, Boolean odDocsAreRunning);
  176. void    SetRunItemsForRunningState(DialogPtr dialog, Boolean odDocsAreRunning);
  177. void    SetRunItemsForStoppedState(DialogPtr dialog);
  178. void    SetupRunItemsFirstTime(DialogPtr dialog, Boolean sysProcIsRunning,
  179.                                 Boolean odDocsAreRunning);
  180. OSErr    QuitSystemProcess(ProcessSerialNumber* psn);
  181. static pascal OSErr    HandleQuit( const AppleEvent*, AppleEvent*, long );
  182.  
  183. inline StringHandle GETSTRING(short resID)
  184. {
  185. #if ODDebug
  186.     StringHandle h = GetString(resID);
  187.     if (!h)
  188.         DebugStr("\pGetString failed. I suggest 'es' now.");
  189.     return h;
  190. #else
  191.     return GetString(resID);
  192. #endif
  193. }
  194.  
  195. inline void GETINDSTRING(StringPtr string, short resID, short index)
  196. {
  197.  
  198.     GetIndString(string, resID, index);
  199. #if ODDebug
  200.     if (!string[0])
  201.         DebugStr("\pGetIndString returned a NULL string. Is this right?");
  202. #endif
  203. }
  204. #if 0
  205. //------------------------------------------------------------------------------
  206. // CopyPascalString
  207. //------------------------------------------------------------------------------
  208.  
  209. inline void CopyPascalString(StringPtr destStr, StringPtr srcStr)
  210.             { BlockMoveData(srcStr, destStr, srcStr[0] + 1); }
  211. #endif /* 0 */
  212. //------------------------------------------------------------------------------
  213. // ODSetupDebugStr
  214. //------------------------------------------------------------------------------
  215.  
  216. inline void ODSetupDebugStr(char* cString)
  217.             { DebugStr(c2pstr(cString)); }
  218.  
  219. //------------------------------------------------------------------------------
  220. // AttachUserItemProc
  221. //------------------------------------------------------------------------------
  222.  
  223. static void AttachUserItemProc (DialogPtr dlog, short item, UserItemUPP proc)
  224. {
  225.     Rect        itemRect;
  226.     short        itemType;
  227.     Handle        itemHandle;
  228.     
  229.     GetDialogItem (dlog, item, &itemType, &itemHandle, &itemRect);
  230.     SetDialogItem (dlog, item, itemType, (Handle) proc, &itemRect);
  231. }
  232.  
  233. //------------------------------------------------------------------------------
  234. // PlotArrowIcon
  235. //------------------------------------------------------------------------------
  236.  
  237. static void PlotArrowIcon(DialogPtr dlog, short item)
  238. {
  239.     RgnHandle    tempRgn = NewRgn();
  240.     Handle        icon;
  241.     Rect        arrowRect;
  242.     short        itemType;
  243.     Handle        itemHandle;
  244.     GrafPtr        savePort;
  245.  
  246.     GetPort(&savePort);
  247.     SetPort(dlog);
  248.     GetClip(tempRgn);
  249.     GetDialogItem(dlog, kArrowControl, &itemType, &itemHandle, &arrowRect);
  250.     ClipRect (&arrowRect);
  251.     arrowRect.bottom = arrowRect.top + 32;
  252.     arrowRect.right = arrowRect.left + 32;
  253.  
  254.     switch (item)
  255.     {
  256.         case kArrowControl:
  257.             icon = GetResource('ICON', kNormalIconID);
  258.             break;
  259.         case kArrowTop:
  260.             icon = GetResource('ICON', kUpArrowIconID);
  261.             break;
  262.         case kArrowBottom:
  263.             icon = GetResource('ICON', kDownArrowIconID);
  264.             break;
  265.     }
  266.  
  267.     PlotIcon(&arrowRect, icon);
  268.  
  269.     SetClip(tempRgn);
  270.     DisposeRgn(tempRgn);
  271.     SetPort(savePort);    
  272. }
  273.     
  274. //------------------------------------------------------------------------------
  275. // MyUserItemProc
  276. //------------------------------------------------------------------------------
  277.  
  278. pascal void MyUserItemProc (DialogPtr dlog, short item)
  279. {
  280.     Rect        itemRect;
  281.     short        itemType;
  282.     Handle        itemHandle;
  283.     
  284.     GetDialogItem (dlog, item, &itemType, &itemHandle, &itemRect);
  285.     
  286.     switch (item) {
  287.     
  288.         case kArrowControl :
  289.         case kArrowTop :
  290.         case kArrowBottom :
  291.             PlotArrowIcon(dlog, item);
  292.             break;
  293.     
  294.         case kOKHilite : // can be done automatically by Dialog Mgr.
  295. //            PenNormal ();
  296. //            PenSize (3, 3);
  297. //            FrameRoundRect (&itemRect, 16, 16);
  298.             break;
  299.     }
  300. }
  301.  
  302. //------------------------------------------------------------------------------
  303. // MenuChoice
  304. //------------------------------------------------------------------------------
  305.  
  306. static Boolean MenuChoice (long menuMessage)
  307. {
  308.     Boolean        continueRunning = true;
  309.     
  310.     short        whichMenu = menuMessage >> 16;
  311.     short        whichItem = menuMessage & 0x0000FFFF;
  312.     
  313.     switch (whichMenu) {
  314.     
  315.         case kAppleMenuID :
  316.             if (whichItem == kAboutItem)
  317.             {
  318.                 Handle h = GetResource('PICT', 128);
  319.                 if (h)
  320.                     Alert(kAboutBox, NULL);
  321.             }
  322.             else
  323.             {
  324.                 Str255        name;
  325.                 GetMenuItemText (GetMenuHandle (kAppleMenuID), whichItem, name);
  326.                 OpenDeskAcc (name);
  327.             }
  328.             break;
  329.         
  330.         case kFileMenuID :
  331.             continueRunning = false;
  332.             break;
  333.     }
  334.     
  335.     HiliteMenu (0);
  336.     return continueRunning;
  337. }
  338.  
  339. //------------------------------------------------------------------------------
  340. // InitToolbox
  341. //------------------------------------------------------------------------------
  342.  
  343. static void InitToolbox ()
  344. {
  345.     MaxApplZone ();                    
  346.     InitGraf (&qd.thePort);
  347.     InitFonts ();
  348.     InitWindows ();
  349.     InitMenus ();
  350.     TEInit ();
  351.     InitDialogs (nil);
  352.     
  353.     SetMenuBar (GetNewMBar (kMenuBarID));
  354.     MenuHandle        appleMenu = GetMenuHandle (kAppleMenuID);
  355.     AppendResMenu (appleMenu, 'DRVR');
  356.     
  357.     InvalMenuBar ();
  358. }
  359.  
  360. //------------------------------------------------------------------------------
  361. // SetDialogMemorySize
  362. //------------------------------------------------------------------------------
  363.  
  364. static void SetDialogMemorySize (DialogPtr dlog, Size size)
  365. {
  366.     long        kilobytes = size / 1024;
  367.     Str255        text;
  368.     Rect        itemRect;
  369.     short        itemType;
  370.     Handle        itemHandle;
  371.     
  372.     GetDialogItem (dlog, kSizeText, &itemType, &itemHandle, &itemRect);
  373.     
  374.     NumToString (kilobytes, text);
  375.     SetDialogItemText (itemHandle, text);
  376. }
  377.  
  378. //------------------------------------------------------------------------------
  379. // main
  380. //------------------------------------------------------------------------------
  381.  
  382. OSErr    gSetDefaultSizeError = noErr;
  383. short    gMyResFileRefNum;
  384. Size    gSize = kDocStubDefaultSize;
  385. FSSpec    gPrefsFileSpec;
  386.  
  387. Boolean    gRunning = true;
  388.  
  389. void main()
  390. {
  391.     gMyResFileRefNum = CurResFile();
  392.  
  393.     InitToolbox ();    
  394.  
  395.     AEEventHandlerUPP handlerUPP = NewAEEventHandlerProc(HandleQuit);
  396.     if (!handlerUPP ||
  397.             AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  398.                                     handlerUPP, 0, false))
  399.         StopAlert(kFatalStartupError, NULL);
  400.  
  401.     // Try to create/open a prefs file to work with.
  402.     short permissions = fsRdWrPerm;
  403.     short prefs = OpenODPrefsResFile (true, permissions);
  404.     if (prefs < 0)
  405.     {
  406.         CautionAlert(kCantWritePreferencesID, NULL);
  407.         permissions = fsRdPerm;
  408.         prefs = OpenODPrefsResFile(true, permissions);
  409.     }
  410.     CloseResFile(prefs);
  411.  
  412. //    ODSetUpPrefs*    prefsAccessor = new ODSetUpPrefs(prefs, permissions);
  413.  
  414.     SetWindowPos(); // DO THIS BEFORE GetNewDialog
  415.     DialogPtr    d = GetNewDialog (kMainDialogID, nil, (WindowPtr) -1);
  416.     if (!d)
  417.         StopAlert(kFatalStartupError, NULL);
  418.  
  419.     // Hard-coded values. I hope it's OK for the localizers, but probably not.
  420.     //    I tried to make Resorcerer use an ictb, but it was hard to get it to
  421.     //    work right.
  422.     long scriptSmallFontSize;
  423.     scriptSmallFontSize = GetScriptVariable(smSystemScript,
  424.                                                 smScriptSmallFondSize);
  425.     d->txFont    = HiWord(scriptSmallFontSize);
  426.     d->txSize    = LoWord(scriptSmallFontSize);
  427. //    d->txFont = geneva;
  428. //    d->txSize = 9;
  429.  
  430.     DoDialogSetup(d);
  431.  
  432.     ShowWindow (d);
  433.     InitCursor ();
  434.     
  435.     do
  436.     {
  437.         EventRecord            theEvent;
  438.         
  439.         CheckForRunningSystemProcesses(d);
  440.         
  441.         if (WaitNextEvent (everyEvent, &theEvent, kSleepTime, nil))
  442.         {
  443.             if (IsDialogEvent (&theEvent))
  444.             {
  445.                 short        itemHit;
  446.                 DialogPtr    theDialog;
  447.  
  448.                 if (DialogSelect (&theEvent, &theDialog, &itemHit) &&
  449.                         (theDialog == d))
  450.                     gRunning = DoDialogHits(d, itemHit);
  451.                 else
  452.                 {
  453.                     if (theEvent.what == keyDown || theEvent.what == autoKey)
  454.                     {
  455.                         if (theEvent.modifiers & cmdKey)
  456.                             gRunning = MenuChoice(MenuKey
  457.                                             (theEvent.message & charCodeMask));
  458.                     }
  459.                     if (theEvent.what == kHighLevelEvent)
  460.                         AEProcessAppleEvent(&theEvent);
  461.                 }
  462.             }
  463.             else
  464.             {
  465.                 switch (theEvent.what)
  466.                 {
  467.                     case mouseDown :
  468.                     {
  469.                         WindowPtr    win;
  470.                         short        part = FindWindow (theEvent.where, &win);
  471.                         
  472.                         switch (part)
  473.                         {
  474.                             case inMenuBar :
  475.                                 gRunning = MenuChoice (MenuSelect (theEvent.where));
  476.                                 break;
  477.                             
  478.                             case inSysWindow :
  479.                                 SystemClick (&theEvent, win);
  480.                                 break;
  481.                             
  482.                             case inDrag :
  483.                             {
  484.                                 Rect    limitRect = { -20000, -20000, 20000, 20000 };
  485.                                 DragWindow (win, theEvent.where, &limitRect); 
  486.                             }
  487.                                 break;
  488.                             
  489.                             case inGoAway :
  490.                                 if (TrackGoAway (win, theEvent.where))
  491.                                     gRunning = false;
  492.                                 break;
  493.                         }
  494.                     }
  495.                         break;
  496.  
  497.                     case keyDown :
  498.                     case autoKey :
  499.                         if (theEvent.modifiers & cmdKey)
  500.                             gRunning = MenuChoice (MenuKey (theEvent.message & charCodeMask));
  501.                         break;
  502.  
  503.                     case kHighLevelEvent:
  504.                         AEProcessAppleEvent(&theEvent);
  505.                 }
  506.             }
  507.         }    
  508.     }
  509.     while (gRunning);
  510.  
  511.     DisplayFinalErrors();
  512.     WriteWindowPos(d);
  513. //    delete prefsAccessor;
  514. //    CloseResFile(prefs);
  515.     DisposeDialog (d);
  516. }
  517.  
  518. //------------------------------------------------------------------------------
  519. // DisplayFinalErrors
  520. //------------------------------------------------------------------------------
  521.  
  522. void DisplayFinalErrors()
  523. {
  524.     if (gSetDefaultSizeError)
  525.         CautionAlert(kCantWriteDefaultSizeID, NULL);
  526. }
  527.  
  528. //------------------------------------------------------------------------------
  529. // DoDialogSetup
  530. //------------------------------------------------------------------------------
  531.  
  532. void DoDialogSetup(DialogPtr dialog)
  533. {
  534.     Rect                itemRect;
  535.     short                itemType;
  536.     Handle                itemHandle;
  537.     Str255                tempString;
  538.     FSSpec                ignore;
  539.     ODSetUpPrefs        prefs(-1, 0);
  540.  
  541.     AttachUserItemProc (dialog, kArrowControl, gUserItemUPP);
  542.     AttachUserItemProc (dialog, kArrowTop, gUserItemUPP);
  543.     AttachUserItemProc (dialog, kArrowBottom, gUserItemUPP);
  544.     AttachUserItemProc (dialog, kOKHilite, gUserItemUPP);
  545.     
  546.     if (prefs.GetDefaultSize(gSize))
  547.         ODSetupDebugStr("Unexpectedly got an error from GetODDefaultSize");
  548.     else
  549.         SetDialogMemorySize(dialog, gSize);
  550.  
  551.     // SET UP START BUTTON AND BUTTON TEXT
  552.         // THIS WILL SET THE DEFAULT "STOPPED" STATE
  553.     GetDialogItem(dialog, kProcessInfoText, &itemType, &itemHandle,
  554.                     &itemRect);
  555.     CopyPascalString(tempString, *GETSTRING(kOpenDocIsStoppedID));
  556.     SetDialogItemText(itemHandle, tempString);
  557.  
  558.         // THIS WILL CHANGE IT IF IT NEEDS TO
  559.     CheckForRunningSystemProcesses(dialog);
  560.  
  561.     // STARTUP CHOICES
  562.     if (OurAliasFileIsInStartupFolder(&ignore))
  563.         GetDialogItem(dialog, kAtSysStartupRadio, &itemType, &itemHandle,
  564.                         &itemRect);
  565.     else
  566.         GetDialogItem(dialog, kWhenFirstDocOpenedRadio, &itemType, &itemHandle,
  567.                     &itemRect);
  568.     SetControlValue((ControlHandle)itemHandle, kSelected);
  569.     
  570.     // SHUTDOWN CHOICES
  571.     if (prefs.GetRunTilSysShutdown())
  572.         GetDialogItem(dialog, kAtSysShutdownRadio, &itemType, &itemHandle,
  573.                         &itemRect);
  574.     else
  575.         GetDialogItem(dialog, kWhenLastDocClosedRadio, &itemType, &itemHandle,
  576.                         &itemRect);
  577.     SetControlValue((ControlHandle)itemHandle, kSelected);
  578. }
  579.  
  580. //------------------------------------------------------------------------------
  581. // DoDialogHits
  582. //
  583. //    Returns whether we should keep gRunning.
  584. //------------------------------------------------------------------------------
  585.  
  586. Boolean DoDialogHits(DialogPtr dialog, short itemHit)
  587. {
  588.     Boolean    shouldKeepRunning = true;
  589.  
  590.     switch (itemHit)
  591.     {
  592.         case kCancelButton :
  593. //            sz = originalSize; // used to have an OK, Cancel interface.
  594.         case kOKButton :
  595.             shouldKeepRunning = false;
  596.             break;
  597.         
  598.         case kArrowBottom :
  599.         case kArrowTop :
  600.             DoMemorySettingHits(dialog, itemHit);
  601.             break;
  602.  
  603.         case kAtSysStartupRadio :
  604.         case kWhenFirstDocOpenedRadio :
  605.         case kAtSysShutdownRadio :
  606.         case kWhenLastDocClosedRadio :
  607.             DoWhenToRunHits(dialog, itemHit);
  608.             break;
  609.  
  610.         case kStartStopButton :
  611.             DoStopStartButtonHits(dialog, itemHit);
  612.             break;
  613.     }
  614.     
  615.     return shouldKeepRunning;
  616. }
  617.  
  618. //------------------------------------------------------------------------------
  619. // DoWhenToRunHits
  620. //------------------------------------------------------------------------------
  621.  
  622. void DoWhenToRunHits(DialogPtr dialog, short itemHit)
  623. {
  624.     Rect                itemRect;
  625.     short                itemType;
  626.     Handle                itemHandle;
  627.     ProcessSerialNumber    psn = {0, kNoProcess};
  628.     ODSetUpPrefs        prefs(-1, 0);
  629.     Boolean                settingPrefsWorked;
  630.     Boolean                sendingMessageWorked;
  631.  
  632.     // FIRST JUST HANDLE THE RADIO BUTTON SWITCHING
  633.     switch (itemHit)
  634.     {
  635.         case kAtSysStartupRadio :
  636.             GetDialogItem(dialog, kAtSysStartupRadio, &itemType, &itemHandle,
  637.                         &itemRect);
  638.             if (GetControlValue((ControlHandle)itemHandle) != kSelected)
  639.             {
  640.                 // PLACE ALIAS IN STARTUP ITEMS FOLDER
  641.                 if (AliasSystemProcessToStartupFolder())
  642.                 {
  643.                     SetControlValue((ControlHandle)itemHandle, kSelected);
  644.                     GetDialogItem(dialog, kWhenFirstDocOpenedRadio, &itemType,
  645.                                 &itemHandle, &itemRect);
  646.                     SetControlValue((ControlHandle)itemHandle, !kSelected);
  647.                 }
  648.             }
  649.             break;
  650.         case kWhenFirstDocOpenedRadio :
  651.             GetDialogItem(dialog, kWhenFirstDocOpenedRadio, &itemType, &itemHandle,
  652.                         &itemRect);
  653.             if (GetControlValue((ControlHandle)itemHandle) != kSelected)
  654.             {
  655.                 // REMOVE ALIAS FROM STARTUP ITEMS FOLDER
  656.                 if (RemoveAliasToSystemProcessFromStartupFolder())
  657.                 {
  658.                     SetControlValue((ControlHandle)itemHandle, kSelected);
  659.                     GetDialogItem(dialog, kAtSysStartupRadio, &itemType,
  660.                                 &itemHandle, &itemRect);
  661.                     SetControlValue((ControlHandle)itemHandle, !kSelected);
  662.                 }
  663.             }
  664.             break;
  665.         case kAtSysShutdownRadio :
  666.             GetDialogItem(dialog, kAtSysShutdownRadio, &itemType, &itemHandle,
  667.                         &itemRect);
  668.             if (GetControlValue((ControlHandle)itemHandle) != kSelected)
  669.             {
  670.                 // SET PREFERENCES AND NOTIFY ANY RUNNING SYSTEM PROCESSES
  671.                 settingPrefsWorked = !prefs.SetRunTilSysShutdown(true);
  672.                 sendingMessageWorked = !SendControlCall(dialog, &psn,
  673.                                                         kRunUntilQuitEvent);
  674.                 if (!settingPrefsWorked && !sendingMessageWorked)
  675.                     CautionAlert(kCouldntSetShutDownPreference, NULL);
  676.                 else
  677.                 {
  678.                     SetControlValue((ControlHandle)itemHandle, kSelected);
  679.                     GetDialogItem(dialog, kWhenLastDocClosedRadio, &itemType,
  680.                                 &itemHandle, &itemRect);
  681.                     SetControlValue((ControlHandle)itemHandle, !kSelected);
  682.                 }
  683.             }
  684.             break;
  685.         case kWhenLastDocClosedRadio :
  686.             GetDialogItem(dialog, kWhenLastDocClosedRadio, &itemType, &itemHandle,
  687.                         &itemRect);
  688.             if (GetControlValue((ControlHandle)itemHandle) != kSelected)
  689.             {
  690.                 // SET PREFERENCES AND NOTIFY ANY RUNNING SYSTEM PROCESSES
  691.                 settingPrefsWorked = !prefs.SetRunTilSysShutdown(false);
  692.                 sendingMessageWorked = !SendControlCall(dialog, &psn,
  693.                                                         kShutdownAtLastDocQuit);
  694.                 if (!settingPrefsWorked && !sendingMessageWorked)
  695.                     CautionAlert(kCouldntSetShutDownPreference, NULL);
  696.                 else
  697.                 {
  698.                     SetControlValue((ControlHandle)itemHandle, kSelected);
  699.                     GetDialogItem(dialog, kAtSysShutdownRadio, &itemType,
  700.                                 &itemHandle, &itemRect);
  701.                     SetControlValue((ControlHandle)itemHandle, !kSelected);
  702.                 }
  703.             }
  704.             break;
  705.     }
  706. }
  707.  
  708. //------------------------------------------------------------------------------
  709. // SendControlCall
  710. //
  711. //    This function contains logic about whether or not to bother sending the
  712. //    control message at all!
  713. //
  714. //    Send a message to the system process.
  715. //
  716. //    The psn parameter is only needed for certain constants. If furnished, it
  717. //    will be used, but if psn.lowLongOfPSN == kNoProcess, then we will try
  718. //    to find and launch the system process.
  719. //
  720. //    kNoMessage                - psn is required.
  721. //    kStartAtSysStartup        - this is currently not supported because it's not
  722. //                                needed
  723. //    kStartAtFirstDocOpen    -  this is currently not supported because it's not
  724. //                                needed
  725. //    kRunUntilQuitEvent        - psn is not required.
  726. //    kShutdownAtLastDocQuit    - psn is not required.
  727. //------------------------------------------------------------------------------
  728.  
  729. #define CATCHERROR(x) error = x; if (error) goto cleanup;
  730.  
  731. OSErr SendControlCall(DialogPtr dialog, ProcessSerialNumber* psn,
  732.                         long controlConstant)
  733. {
  734.     OSErr    error = noErr;
  735.     Boolean    odDocsAreRunning;
  736.     Boolean    sysProcIsRunning;
  737.  
  738.     // IF WE WERE NOT GIVEN A PSN TO USE, LOOK FOR THE SYSTEM PROCESS AND LAUNCH
  739.     //    IT IF NECESSARY.
  740.     if (psn->lowLongOfPSN == kNoProcess)
  741.     {
  742.         if (controlConstant == kRunUntilQuitEvent
  743.             || controlConstant == kShutdownAtLastDocQuit)
  744.         {
  745.             AreODProcessesRunning(dialog, psn, odDocsAreRunning);
  746.             sysProcIsRunning = !(psn->lowLongOfPSN == kNoProcess);
  747.             // SYSTEM PROCESS MAY NOT BE RUNNING (USER MAY HAVE LAUNCHED
  748.             //    LAUNCHER INSTEAD). SO MUST LAUNCH SYSTEM PROCESS WHEN WE WANT
  749.             //    OPENDOC TO STAY LOADED FOREVER.
  750.             if (odDocsAreRunning
  751.                     && (controlConstant == kRunUntilQuitEvent)
  752.                     && !sysProcIsRunning)
  753.                 error = LaunchSystemProcess(psn);
  754.         }
  755.     }
  756.  
  757.     if (!error)
  758.     {
  759.         AEAddressDesc    address = {typeNull, NULL};
  760.         AppleEvent        message = {typeNull, NULL};
  761.         AppleEvent        reply = {typeNull, NULL};
  762.  
  763.         CATCHERROR(AECreateDesc(typeProcessSerialNumber, (Ptr)psn, sizeof(*psn),
  764.                                 &address));
  765.         CATCHERROR(AECreateAppleEvent(kODShellSignature, kSysProcControlEventID,
  766.                         &address, kAutoGenerateReturnID, kAnyTransactionID,
  767.                         &message));
  768.         CATCHERROR(AEPutParamPtr(&message, kControlMessageKeyword, typeInteger,
  769.                                     (Ptr)&controlConstant,
  770.                                     sizeof(controlConstant)));
  771.         CATCHERROR(AESend(&message, &reply,
  772.                             kAENoReply + kAENeverInteract + kAEDontRecord,
  773.                             kAEHighPriority, kAEDefaultTimeout,
  774.                             (AEIdleUPP)kODNULL, (AEFilterUPP)kODNULL));
  775.  
  776.   cleanup:
  777.           AEDisposeDesc(&address);
  778.           AEDisposeDesc(&message);
  779.           AEDisposeDesc(&reply);
  780.     }
  781.  
  782.     return error;
  783. }
  784.  
  785. //------------------------------------------------------------------------------
  786. // DoMemorySettingHits
  787. //
  788. //    There's a small chance that we might hit a window and do that opposite of
  789. //    what the button says.
  790. //------------------------------------------------------------------------------
  791.  
  792. void DoStopStartButtonHits(DialogPtr dialog, short itemHit)
  793. {
  794.     ProcessSerialNumber    psn;
  795.     Boolean                odDocsAreRunning;
  796.     Boolean                systemProcessIsRunning;
  797.  
  798.     AreODProcessesRunning(dialog, &psn, odDocsAreRunning);
  799.     systemProcessIsRunning = !(psn.lowLongOfPSN == kNoProcess);
  800.     if (systemProcessIsRunning)
  801.     {
  802.         if (QuitSystemProcess(&psn))
  803.             CautionAlert(kCouldntShutDownOpenDoc, NULL);
  804.     }
  805.     else
  806.     {
  807.         if (LaunchSystemProcess(&psn))
  808.             CautionAlert(kCouldntStartupOpenDoc, NULL);
  809.     }
  810. }
  811.  
  812. //------------------------------------------------------------------------------
  813. // DoMemorySettingHits
  814. //------------------------------------------------------------------------------
  815.  
  816. #define kSizeIncrement        (32 * 1024L)
  817. #define kMaximumSize        (1024L * 1024L * 64)
  818.  
  819. void DoMemorySettingHits(DialogPtr dialog, short itemHit)
  820. {
  821.     short            itemType;
  822.     Handle            itemHandle;
  823.     Rect            arrowRect;
  824.     Point            mousePoint;
  825.     long            ignore;
  826.     GrafPtr            savePort;
  827.     ODSetUpPrefs    prefs(-1, 0);
  828.  
  829.     switch (itemHit)
  830.     {
  831.         case kArrowBottom :
  832.             GetDialogItem(dialog, kArrowBottom, &itemType,
  833.                             &itemHandle, &arrowRect);
  834.             PlotArrowIcon(dialog, itemHit);
  835.             GetPort(&savePort);
  836.             SetPort(dialog);
  837.             do
  838.             {
  839.                 GetMouse(&mousePoint);
  840.                 if (PtInRect(mousePoint, &arrowRect))
  841.                 {
  842.                     gSize -= kSizeIncrement;
  843.                     if (gSize < kDocStubMinHeapSize)
  844.                         gSize = kDocStubMinHeapSize;
  845.                     else
  846.                         SetDialogMemorySize (dialog, gSize);
  847.                     Delay(8, &ignore);
  848.                 }
  849.             }
  850.             while (StillDown());
  851.             SetPort(savePort);
  852.             PlotArrowIcon(dialog, kArrowControl);
  853.             if(prefs.SetDefaultSize(gSize))
  854.                 gSetDefaultSizeError = 1; // dummy value for now
  855.             break;
  856.             
  857.         case kArrowTop :
  858.             GetDialogItem(dialog, kArrowTop, &itemType,
  859.                             &itemHandle, &arrowRect);
  860.             PlotArrowIcon(dialog, itemHit);
  861.             GetPort(&savePort);
  862.             SetPort(dialog);
  863.             do
  864.             {
  865.                 GetMouse(&mousePoint);
  866.                 if (PtInRect(mousePoint, &arrowRect))
  867.                 {
  868.                     gSize += kSizeIncrement;
  869.                     if (gSize > kMaximumSize)
  870.                         gSize = kMaximumSize;
  871.                     else
  872.                         SetDialogMemorySize(dialog, gSize);
  873.                     Delay(8, &ignore);
  874.                 }
  875.             }
  876.             while (StillDown());
  877.             SetPort(savePort);
  878.             PlotArrowIcon(dialog, kArrowControl);
  879.             if(prefs.SetDefaultSize(gSize))
  880.                 gSetDefaultSizeError = 1; // dummy value for now
  881.             break;
  882.     }
  883. }
  884.  
  885. //------------------------------------------------------------------------------
  886. // SetWindowPos
  887. //------------------------------------------------------------------------------
  888.  
  889. void SetWindowPos()
  890. {
  891.     Rect        dialogRect;
  892.     RgnHandle    windowRgn = NewRgn();
  893.     RgnHandle    intersectRgn = NewRgn();
  894.     
  895.     short        saveResFile = CurResFile();
  896.     UseResFile(gMyResFileRefNum);
  897.  
  898.     DialogTHndl    hResource = (DialogTHndl)Get1Resource('DLOG', kMainDialogID);
  899.  
  900.     UseResFile(saveResFile);
  901.     
  902.     dialogRect = (**hResource).boundsRect;
  903.     
  904.     dialogRect.top -= 18; // window title bar height.
  905.  
  906.     RectRgn(windowRgn, &dialogRect);
  907.     SectRgn(windowRgn, GetGrayRgn(), intersectRgn);
  908.     if (!EqualRgn(windowRgn, intersectRgn))
  909.     {
  910.         short    height = dialogRect.bottom - dialogRect.top;
  911.         short    width = dialogRect.right - dialogRect.left;
  912.         
  913.         dialogRect.top = 100;
  914.         dialogRect.left = 100;
  915.         dialogRect.bottom = 100 + height;
  916.         dialogRect.right = 100 + width;
  917.  
  918.         (**hResource).boundsRect = dialogRect;
  919.     }
  920.  
  921.     DisposeRgn(windowRgn);
  922.     DisposeRgn(intersectRgn);
  923. }
  924.  
  925. //------------------------------------------------------------------------------
  926. // WriteWindowPos
  927. //------------------------------------------------------------------------------
  928.  
  929. void WriteWindowPos(DialogPtr dialog)
  930. {
  931.     Rect    dialogRect;
  932.     short    saveResFile = CurResFile();
  933.     
  934.     UseResFile(gMyResFileRefNum);
  935.  
  936.     DialogTHndl    hResource = (DialogTHndl)Get1Resource('DLOG', kMainDialogID);
  937.     
  938.     // GOT THIS INFO FROM INSPECTION IN THE DEBUGGER
  939.     dialogRect.top = -dialog->portBits.bounds.top;
  940.     dialogRect.left = -dialog->portBits.bounds.left;
  941.     dialogRect.bottom = dialogRect.top + dialog->portRect.bottom;
  942.     dialogRect.right = dialogRect.left + dialog->portRect.right;
  943.  
  944.     (**hResource).boundsRect = dialogRect;
  945.     ChangedResource((Handle)hResource);
  946.     WriteResource((Handle)hResource);
  947.  
  948.     UseResFile(saveResFile);
  949. }
  950.  
  951. //------------------------------------------------------------------------------
  952. // CheckForRunningSystemProcesses
  953. //
  954. //    The system process can have kODShellSignature or kODSystemProcessSignature
  955. //    signatures. If we encounter a kODShellSignature app, we ask it if
  956. //    it is the right one. We could also look for the special resource.
  957. //
  958. //    Will return a valid ProcessSerialNumber if a system process is running,
  959. //    otherwise, psn.lowLongOfPSN is set to kNoProcess.
  960. //------------------------------------------------------------------------------
  961.  
  962. void CheckForRunningSystemProcesses(DialogPtr dialog)
  963. {
  964.     ProcessSerialNumber    psn;
  965.     Boolean                odDocsAreRunning;
  966.     Boolean                systemProcessIsRunning;
  967.     
  968.     AreODProcessesRunning(dialog, &psn, odDocsAreRunning);
  969.     systemProcessIsRunning = !(psn.lowLongOfPSN == kNoProcess);
  970.  
  971.     if (odDocsAreRunning && !systemProcessIsRunning)
  972.         // SHOULD TRY TO LAUNCH SYSTEM PROCESS NOW?
  973.         //    NO. WAIT UNTIL I NEED TO
  974.         ;
  975.  
  976.     if (systemProcessIsRunning || odDocsAreRunning)
  977.         SetButtonRunState(dialog, true, odDocsAreRunning);
  978.     else
  979.         SetButtonRunState(dialog, false, odDocsAreRunning);
  980.         
  981. }
  982.  
  983. //------------------------------------------------------------------------------
  984. // AreODProcessesRunning
  985. //
  986. //    The system process can have kODShellSignature or kODSystemProcessSignature
  987. //    signatures. If we encounter a kODShellSignature app, we ask it if
  988. //    it is the right one. We could also look for the special resource.
  989. //
  990. //    Will return a valid ProcessSerialNumber if a system process is running,
  991. //    otherwise, psn.lowLongOfPSN is set to kNoProcess.
  992. //------------------------------------------------------------------------------
  993.  
  994. void AreODProcessesRunning(DialogPtr dialog, ProcessSerialNumber* psn,
  995.                             Boolean& odDocsAreRunning)
  996. {
  997.     ProcessInfoRec        procInfo;
  998.     OSErr                error = noErr;
  999.     FSSpec                procSpec;
  1000.     Boolean                systemProcessIsRunning = false;
  1001.     ProcessSerialNumber    iteratorPSN; // used to iterate only.
  1002.  
  1003.     odDocsAreRunning = false;
  1004.  
  1005.     psn->highLongOfPSN = 0;
  1006.     psn->lowLongOfPSN = kNoProcess;
  1007.     iteratorPSN.highLongOfPSN = 0;
  1008.     iteratorPSN.lowLongOfPSN = kNoProcess;
  1009.  
  1010.     procInfo.processInfoLength = sizeof(procInfo);
  1011.     procInfo.processName = NULL;
  1012.     procInfo.processAppSpec = &procSpec;
  1013.  
  1014.     while (error != procNotFound)
  1015.     {
  1016.         error = GetNextProcess(&iteratorPSN);
  1017.         if (!error)
  1018.             error = GetProcessInformation(&iteratorPSN, &procInfo);
  1019.         if (!error)
  1020.         {
  1021.             FInfo    finderInfo;
  1022.             
  1023.             error = FSpGetFInfo(&procSpec, &finderInfo);
  1024.             if (!error)
  1025.             {
  1026.                 if (finderInfo.fdCreator == kODSystemProcessSignature)
  1027.                 {
  1028.                     *psn = procInfo.processNumber;
  1029.                     systemProcessIsRunning = true;
  1030.                     continue;
  1031.                 }
  1032.                 else if (finderInfo.fdCreator == kODShellSignature
  1033.                             && finderInfo.fdType == 'APPL')
  1034.                 {
  1035.                     if (!SendControlCall(dialog, &procInfo.processNumber,
  1036.                                             kNoMessage))
  1037.                     {
  1038.                         *psn = procInfo.processNumber;
  1039.                         systemProcessIsRunning = true;
  1040.                         continue;
  1041.                     }
  1042.                 }
  1043.                 if (!odDocsAreRunning &&
  1044.                             PlatformFile::IsOpenDocDocument(finderInfo.fdType,
  1045.                                                         finderInfo.fdCreator))
  1046.                     odDocsAreRunning = true;
  1047.             }
  1048.         }
  1049.     }
  1050. }
  1051.  
  1052. //------------------------------------------------------------------------------
  1053. // SetButtonRunState
  1054. //
  1055. //    gSysProcIsRunning is set as a side effect here. Gross, but it allows us to
  1056. //    use gSysProcIsRunning as "previous state" flag that we can check to make
  1057. //    sure we don't redraw the button more than we have to. Similarly with
  1058. //    gODDocsAreRunning
  1059. //------------------------------------------------------------------------------
  1060. #if 0
  1061. Boolean    gSysProcIsRunning = false;
  1062. Boolean    gODDocsAreRunning = false;
  1063. Boolean    gFirstTimeThrough = true;
  1064.  
  1065. void SetButtonRunState(DialogPtr dialog, Boolean sysProcIsRunning,
  1066.                         Boolean odDocsAreRunning)
  1067. {
  1068.     short        itemType;
  1069.     Handle        itemHandle;
  1070.     Rect        itemRect;
  1071.     Str255        tempString;
  1072.     const short kActive = 0;
  1073.  
  1074.     if (sysProcIsRunning && odDocsAreRunning)
  1075.     if (!sysProcIsRunning && odDocsAreRunning)
  1076.     
  1077.     if (sysProcIsRunning && !odDocsAreRunning)
  1078.  
  1079.     if (!sysProcIsRunning && !odDocsAreRunning)
  1080.  
  1081.     if (gSysProcIsRunning)
  1082.     {
  1083.         if (!sysProcIsRunning)
  1084.         {    
  1085.             // SET TO STOPPED STATE
  1086.             gSysProcIsRunning = false;
  1087.             
  1088.             // BUTTON
  1089.             GetDialogItem(dialog, kStartStopButton, &itemType, &itemHandle,
  1090.                             &itemRect);
  1091.             CopyPascalString(tempString, *GETSTRING(kStartID));
  1092.             SetControlTitle((ControlHandle)itemHandle, tempString);
  1093.             HiliteControl((ControlHandle)itemHandle, kActive);
  1094.  
  1095.             // TEXT
  1096.             GetDialogItem(dialog, kProcessInfoText, &itemType, &itemHandle,
  1097.                             &itemRect);
  1098.             CopyPascalString(tempString, *GETSTRING(kOpenDocIsStoppedID));
  1099.             SetDialogItemText(itemHandle, tempString);
  1100.         }
  1101.     }
  1102.     else
  1103.     {
  1104.         if (sysProcIsRunning)
  1105.         {
  1106.             // SET TO RUNNING STATE
  1107.             gSysProcIsRunning = true;
  1108.             
  1109.             // BUTTON
  1110.             GetDialogItem(dialog, kStartStopButton, &itemType, &itemHandle,
  1111.                             &itemRect);
  1112.             CopyPascalString(tempString, *GETSTRING(kStopID));
  1113.             SetControlTitle((ControlHandle)itemHandle, tempString);
  1114.  
  1115.             if (odDocsAreRunning)
  1116.                 HiliteControl((ControlHandle)itemHandle, kControlInactivePart);
  1117.             else
  1118.                 HiliteControl((ControlHandle)itemHandle, kActive);
  1119.  
  1120.             GetDialogItem(dialog, kProcessInfoText, &itemType, &itemHandle,
  1121.                             &itemRect);
  1122.             
  1123.             // TEXT
  1124.             if (odDocsAreRunning && !gODDocsAreRunning)
  1125.             {
  1126.                 gODDocsAreRunning = true;
  1127.             
  1128.                 CopyPascalString(tempString,
  1129.                                     *GETSTRING(kOpenDocIsRunningNoStopID));
  1130.                 SetDialogItemText(itemHandle, tempString);
  1131.             }
  1132.             else if (!odDocsAreRunning && gODDocsAreRunning)
  1133.             {
  1134.                 CopyPascalString(tempString,
  1135.                                     *GETSTRING(kOpenDocIsRunningID));
  1136.                 SetDialogItemText(itemHandle, tempString);
  1137.             }
  1138.         }
  1139.     }
  1140.     gFirstTimeThrough = false;
  1141. }
  1142. #endif /* 0 */
  1143.  
  1144. //------------------------------------------------------------------------------
  1145. // SetupRunItemsFirstTime
  1146. //------------------------------------------------------------------------------
  1147.  
  1148. void SetupRunItemsFirstTime(DialogPtr dialog, Boolean sysProcIsRunning,
  1149.                             Boolean odDocsAreRunning)
  1150. {
  1151.     if (!sysProcIsRunning && !odDocsAreRunning)
  1152.         SetRunItemsForStoppedState(dialog);
  1153.     else
  1154.         SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1155. }
  1156.  
  1157. //------------------------------------------------------------------------------
  1158. // SetRunTextForRunningState
  1159. //------------------------------------------------------------------------------
  1160.  
  1161. void SetRunTextForRunningState(DialogPtr dialog, Boolean odDocsAreRunning)
  1162. {
  1163.     short        itemType;
  1164.     Rect        itemRect;
  1165.     Handle        itemHandle;
  1166.     Str255        tempString;
  1167.     const short kActive = 0;
  1168.  
  1169.     GetDialogItem(dialog, kProcessInfoText, &itemType, &itemHandle,
  1170.                     &itemRect);
  1171.     if (odDocsAreRunning)
  1172.     {
  1173.         CopyPascalString(tempString,
  1174.                             *GETSTRING(kOpenDocIsRunningNoStopID));
  1175.         SetDialogItemText(itemHandle, tempString);
  1176.     }
  1177.     else
  1178.     {
  1179.         CopyPascalString(tempString,
  1180.                             *GETSTRING(kOpenDocIsRunningID));
  1181.         SetDialogItemText(itemHandle, tempString);
  1182.     }
  1183. }
  1184.  
  1185. //------------------------------------------------------------------------------
  1186. // SetRunItemsForRunningState
  1187. //------------------------------------------------------------------------------
  1188.  
  1189. void SetRunItemsForRunningState(DialogPtr dialog, Boolean odDocsAreRunning)
  1190. {
  1191.     short        itemType;
  1192.     Handle        itemHandle;
  1193.     Rect        itemRect;
  1194.     Str255        tempString;
  1195.     const short kActive = 0;
  1196.  
  1197.     // BUTTON
  1198.     GetDialogItem(dialog, kStartStopButton, &itemType, &itemHandle,
  1199.                     &itemRect);
  1200.     CopyPascalString(tempString, *GETSTRING(kStopID));
  1201.     SetControlTitle((ControlHandle)itemHandle, tempString);
  1202.  
  1203.     if (odDocsAreRunning)
  1204.         HiliteControl((ControlHandle)itemHandle, kControlInactivePart);
  1205.     else
  1206.         HiliteControl((ControlHandle)itemHandle, kActive);
  1207.  
  1208.     // TEXT
  1209.     SetRunTextForRunningState(dialog, odDocsAreRunning);
  1210. }
  1211.  
  1212. //------------------------------------------------------------------------------
  1213. // SetRunItemsForStoppedState
  1214. //------------------------------------------------------------------------------
  1215.  
  1216. void SetRunItemsForStoppedState(DialogPtr dialog)
  1217. {
  1218.     short        itemType;
  1219.     Handle        itemHandle;
  1220.     Rect        itemRect;
  1221.     Str255        tempString;
  1222.     const short kActive = 0;
  1223.  
  1224.     // BUTTON
  1225.     GetDialogItem(dialog, kStartStopButton, &itemType, &itemHandle,
  1226.                     &itemRect);
  1227.     CopyPascalString(tempString, *GETSTRING(kStartID));
  1228.     SetControlTitle((ControlHandle)itemHandle, tempString);
  1229.     HiliteControl((ControlHandle)itemHandle, kActive);
  1230.  
  1231.     // TEXT
  1232.     GetDialogItem(dialog, kProcessInfoText, &itemType, &itemHandle,
  1233.                     &itemRect);
  1234.     CopyPascalString(tempString, *GETSTRING(kOpenDocIsStoppedID));
  1235.     SetDialogItemText(itemHandle, tempString);
  1236. }
  1237.  
  1238. //------------------------------------------------------------------------------
  1239. // SetButtonRunState
  1240. //
  1241. //    Using a transition table so that I only make changes to the dialog when I
  1242. //    need to.
  1243. //------------------------------------------------------------------------------
  1244.  
  1245. enum
  1246. {
  1247.     kSysProcIsRunning = ( 1 << 0 ), // used whenever sysProcIsRunning is true
  1248.     kODDocsAreRunning = ( 1 << 1 ), // used whenver odDocsAreRunning is true
  1249.     kFirstTimeThrough = ( 1 << 2 )  // only used in initialization of global
  1250. };
  1251.  
  1252. int gODOldSysRunState = kFirstTimeThrough; // only time this bit is used
  1253.  
  1254. void SetButtonRunState(DialogPtr dialog, Boolean sysProcIsRunning,
  1255.                         Boolean odDocsAreRunning)
  1256. {
  1257.     // turn on kSysProcIsRunning bit if sysProcIsRunning is true:
  1258.     int newRunState = ( sysProcIsRunning ) ? kSysProcIsRunning : 0;
  1259.  
  1260.     // turn on kODDocsAreRunning bit if odDocsAreRunning is true:
  1261.     if ( odDocsAreRunning )
  1262.         newRunState |= kODDocsAreRunning;
  1263.         
  1264.     // Note that the kFirstTimeThrough bit is never set in newRunState.
  1265.  
  1266.     // record whether the kFirstTimeThrough bit is set in  gODOldSysRunState:
  1267.     Boolean firstTime = ( gODOldSysRunState & kFirstTimeThrough ) != 0; 
  1268.     
  1269.     if (firstTime)
  1270.     {
  1271.         // this happens only once.
  1272.         
  1273.         SetupRunItemsFirstTime(dialog, sysProcIsRunning, odDocsAreRunning);
  1274.     }
  1275.     else if ( /*firstTime ||*/ newRunState != gODOldSysRunState )
  1276.     {
  1277.         // anything changed?
  1278.  
  1279.         // ~kFirstTimeThrough is a mask of all ones with a zero at ( 1 << 2 )
  1280.         // we are removing the kFirstTimeThrough bit from gODOldSysRunState here:
  1281.         int oldWithoutFirstTime = ( gODOldSysRunState & ~kFirstTimeThrough );
  1282.         
  1283.         // now build a 4 bit integer with the top two bits containing old state:
  1284.         int oldAndNewState = ( oldWithoutFirstTime << 2 ) | newRunState;
  1285.  
  1286.         // table to examine all possible transitions from old to new state:
  1287.         switch ( oldAndNewState )
  1288.         {
  1289.             // gODOldSysRunState == !kODDocsAreRunning && !kSysProcIsRunning
  1290.             case 0x0: //  00 -> 00  => should not occur (huh?)
  1291.                 ODSetupDebugStr("hit a should not occur case");
  1292.                 break; 
  1293.                 
  1294.             case 0x1: //  00 -> 01  => no docs running, but sys proc running
  1295.                         //                (NOW RUNNING, CAN STOP)
  1296.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1297.                 break; 
  1298.             case 0x2: //  00 -> 10  => docs running now, but no sys proc
  1299.                         //                (NOW RUNNING, CAN'T STOP)
  1300.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1301.                 break; 
  1302.             case 0x3: //  00 -> 11  => both running (NOW RUNNING, CAN'T STOP)
  1303.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1304.                 break; 
  1305.             
  1306.             // gODOldSysRunState == !kODDocsAreRunning && kSysProcIsRunning
  1307.             case 0x4: //  01 -> 00  => (NOTHING RUNNING)
  1308.                 SetRunItemsForStoppedState(dialog);
  1309.                 break; 
  1310.             case 0x5: //  01 -> 01  => should not occur (huh?)
  1311.                 ODSetupDebugStr("hit a should not occur case 01 -> 01");
  1312.                 break; 
  1313.             case 0x6: //  01 -> 10  => docs running now, no sys proc
  1314.                         //                (CAN'T STOP)
  1315. //                SetRunTextForRunningState(dialog, odDocsAreRunning);
  1316.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1317.                 break; 
  1318.             case 0x7: //  01 -> 11  => docs running now (CAN'T STOP)
  1319. //                SetRunTextForRunningState(dialog, odDocsAreRunning);
  1320.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1321.                 break; 
  1322.             
  1323.             // gODOldSysRunState == kODDocsAreRunning && !kSysProcIsRunning
  1324.             case 0x8: //  10 -> 00  => (NOTHING RUNNING)
  1325.                 SetRunItemsForStoppedState(dialog);
  1326.                 break; 
  1327.             case 0x9: //  10 -> 01  => docs not running, but sysproc is
  1328.                         //                (CAN STOP)
  1329. //                SetRunTextForRunningState(dialog, odDocsAreRunning);
  1330.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1331.                 break; 
  1332.             case 0xA: //  10 -> 10  => should not occur (huh?)
  1333.                 ODSetupDebugStr("hit a should not occur case 10 -> 10");
  1334.                 break; 
  1335.             case 0xB: //  10 -> 11  => docs running and now sys proc (NO-OP)
  1336. //                SetRunTextForRunningState(dialog, odDocsAreRunning);
  1337.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1338.                 break; 
  1339.             
  1340.             // gODOldSysRunState == kODDocsAreRunning && kSysProcIsRunning
  1341.             case 0xC: //  11 -> 00  => (NOTHING RUNNING)
  1342.                 SetRunItemsForStoppedState(dialog);
  1343.                 break; 
  1344.             case 0xD: //  11 -> 01  => docs no longer running (CAN STOP)
  1345. //                SetRunTextForRunningState(dialog, odDocsAreRunning);
  1346.                 SetRunItemsForRunningState(dialog, odDocsAreRunning);
  1347.                 break; 
  1348.             case 0xE: //  11 -> 10  => sys proc no longer running (NO-OP)
  1349.                 break; 
  1350.             case 0xF: //  11 -> 11  => should not occur (huh?)
  1351.                 ODSetupDebugStr("hit a should not occur case 11 -> 11");
  1352.                 break; 
  1353.             default:
  1354.                 ODSetupDebugStr("default case.");
  1355.                 // huh?
  1356.                 break;
  1357.         } 
  1358.     }
  1359.     
  1360.     gODOldSysRunState = newRunState; // always update old with new state
  1361.     // gODOldSysRunState never has kFirstTimeThrough bit set again
  1362. }
  1363.  
  1364. //------------------------------------------------------------------------------
  1365. // LaunchSystemProcess
  1366. //------------------------------------------------------------------------------
  1367.  
  1368. OSErr LaunchSystemProcess(ProcessSerialNumber* psn)
  1369. {
  1370.     OSErr    error;
  1371.     FSSpec    sysProcSpec;
  1372.     FInfo    finderInfo;
  1373.  
  1374.     error = SystemProcessFileSpecFromName(&sysProcSpec);
  1375.  
  1376.     // just make call to verify the existence of the file
  1377.     if (!error)
  1378.         error = FSpGetFInfo(&sysProcSpec, &finderInfo);
  1379.     
  1380.     if (error)
  1381.         error = SystemProcessFileSpecFromSecretResource(&sysProcSpec);
  1382.         
  1383.     if (!error)
  1384.     {
  1385.         LaunchParamBlockRec    launchPB;
  1386.     
  1387.         launchPB.launchBlockID = extendedBlock;
  1388.         launchPB.launchEPBLength = extendedBlockLen;
  1389.         // HOW ABOUT OTHER FLAGS?
  1390.         launchPB.launchControlFlags = launchContinue
  1391.                                         | launchNoFileFlags
  1392.                                         | launchDontSwitch;
  1393.         launchPB.launchAppSpec = &sysProcSpec;
  1394.         launchPB.launchAppParameters = NULL;
  1395.         
  1396.         error = LaunchApplication(&launchPB);
  1397.         if (!error)
  1398.             *psn = launchPB.launchProcessSN;
  1399.     }
  1400.  
  1401.     return error;
  1402. }
  1403.  
  1404. //------------------------------------------------------------------------------
  1405. // QuitSystemProcess
  1406. //------------------------------------------------------------------------------
  1407.  
  1408. OSErr QuitSystemProcess(ProcessSerialNumber* psn)
  1409. {
  1410.     OSErr            error;
  1411.     AEAddressDesc    address = {typeNull, NULL};
  1412.     AppleEvent        message = {typeNull, NULL};
  1413.     AppleEvent        reply = {typeNull, NULL};
  1414.  
  1415.     CATCHERROR(AECreateDesc(typeProcessSerialNumber, (Ptr)psn, sizeof(*psn),
  1416.                             &address));
  1417.     CATCHERROR(AECreateAppleEvent(kCoreEventClass, kAEQuitApplication,
  1418.                     &address, kAutoGenerateReturnID, kAnyTransactionID,
  1419.                     &message));
  1420.     CATCHERROR(AESend(&message, &reply,
  1421.                         kAENoReply + kAENeverInteract + kAEDontRecord,
  1422.                         kAEHighPriority, kAEDefaultTimeout,
  1423.                         (AEIdleUPP)kODNULL, (AEFilterUPP)kODNULL));
  1424.  
  1425.   cleanup:
  1426.       AEDisposeDesc(&address);
  1427.       AEDisposeDesc(&message);
  1428.       AEDisposeDesc(&reply);
  1429.     
  1430.     return error;
  1431. }
  1432.  
  1433. //------------------------------------------------------------------------------
  1434. //  HandleQuit
  1435. //------------------------------------------------------------------------------
  1436.  
  1437. static pascal OSErr HandleQuit( const AppleEvent*, AppleEvent*, long )
  1438. {
  1439.     gRunning = false;
  1440.  
  1441.     return noErr;
  1442. }
  1443.  
  1444.